
#include <BLabel>
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BTableItem>

#include "StringUtils.h"
#include "VBoxLayoutPanel.h"

VBoxLayoutPanel::VBoxLayoutPanel(BWidget* parent) : BGroupBox(parent)
{
	BGridLayout* gridLayout = new BGridLayout();
	{
		BLabel* nameLabel = new BLabel("name");
		_nameEdit = new BLineEdit();

		_enabledCheckBox = new BCheckBox("enabled");
		_splitableCheckBox = new BCheckBox("splitable");

		BLabel* marginLabel = new BLabel("margin");
		_marginEdit = new BLineEdit();

		BLabel* spacingSpinBox = new BLabel("spacing");
		_spacingSpinBox = new BSpinBox();

		BLabel* partLabel = new BLabel("part");
		_partComboBox = new BComboBox();
		_partComboBox->addItem("None", Part_None);
		_partComboBox->addItem("Top", Part_Top );
		_partComboBox->addItem("Left", Part_Left);
		_partComboBox->addItem("Right", Part_Right);
		_partComboBox->addItem("Bottom", Part_Bottom);
		_partComboBox->addItem("Center", Part_Center);

		gridLayout->addWidget(0, 0, nameLabel);
		gridLayout->addWidget(0, 1, _nameEdit);
		gridLayout->addWidget(1, 0, _enabledCheckBox);
		gridLayout->addWidget(1, 1, _splitableCheckBox);
		gridLayout->addWidget(2, 0, marginLabel);
		gridLayout->addWidget(2, 1, _marginEdit);
		gridLayout->addWidget(3, 0, spacingSpinBox);
		gridLayout->addWidget(3, 1, _spacingSpinBox);
	}

	_policyMenu = new PolicyMenu();
	_stretchSpinBox = new BFloatSpinBox();

	_groupBox = new BGroupBox();
	{
		BLabel* rowLabel = new BLabel("row");
		_rowSpinBox = new BSpinBox(0, 100);
		_rowTableWidget = new BTableWidget();
		_rowTableWidget->setScrollHint(ScrollHint_None);
		_rowTableWidget->setColumnCount(2);
		_rowTableWidget->setColumnLabel(0, "Policy");
		_rowTableWidget->setColumnLabel(1, "Stretch");

		BLabel* columnLabel = new BLabel("column");
		_columnSpinBox = new BSpinBox(0, 100);
		_columnTableWidget = new BTableWidget();
		_columnTableWidget->setScrollHint(ScrollHint_None);
		_columnTableWidget->setColumnCount(2);
		_columnTableWidget->setColumnLabel(0, "Policy");
		_columnTableWidget->setColumnLabel(1, "Stretch");

		BGridLayout* gridLayout = new BGridLayout(_groupBox);
		gridLayout->addWidget(0, 0, rowLabel);
		gridLayout->addWidget(0, 1, _rowSpinBox);
		gridLayout->addWidget(1, 1, _rowTableWidget);
		gridLayout->addWidget(2, 0, columnLabel);
		gridLayout->addWidget(2, 1, _columnSpinBox);
		gridLayout->addWidget(3, 1, _columnTableWidget);
		gridLayout->setColumnPolicy(0, Policy_Preferred);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(gridLayout);
	vlayout->addWidget(_groupBox);

	connect(this, Signal_AssetChanged, &VBoxLayoutPanel::slotAssetChanged);

	connect(_nameEdit, Signal_EditFinished, &VBoxLayoutPanel::slotNameEditFinished);
	connect(_enabledCheckBox, Signal_Toggled, &VBoxLayoutPanel::slotEnabledToggled);
	connect(_splitableCheckBox, Signal_Toggled, &VBoxLayoutPanel::slotSplitableToggled);
	connect(_marginEdit, Signal_EditFinished, &VBoxLayoutPanel::slotMarginEditFinished);
	connect(_spacingSpinBox, Signal_EditFinished, &VBoxLayoutPanel::slotSpacingEditFinished);

	connect(_rowSpinBox, Signal_EditFinished, &VBoxLayoutPanel::slotGridRowEditFinished);
	connect(_columnSpinBox, Signal_EditFinished, &VBoxLayoutPanel::slotGridColumnEditFinished);
	connect(_rowTableWidget, Signal_ItemRightClicked, &VBoxLayoutPanel::slotTableItemRightClicked);

	connect(_policyMenu, Signal_Triggered, &VBoxLayoutPanel::slotPolicyMenuTrigger);
	connect(_stretchSpinBox, Signal_EditFinished, &VBoxLayoutPanel::slotStretchEditFinished);
}

void VBoxLayoutPanel::freshRowTableWidget()
{
	if (BGridLayout* gridLayout = this->asset())
	{
		_rowTableWidget->setRowCount(gridLayout->rowCount());
		for (int r = 0; r < gridLayout->rowCount(); r++)
		{
			Policy policy = gridLayout->rowPolicy(r);
			float stretch = gridLayout->rowStretch(r);
			_rowTableWidget->setRowLabel(r, r);
			_rowTableWidget->setItem(r, 0, PolicyMenu::PolicyText(policy))->setAsset(policy);
			_rowTableWidget->setItem(r, 1, stretch)->setAsset(stretch);
		}
	}
}
void VBoxLayoutPanel::freshColumnTableWidget()
{
	if (BGridLayout* gridLayout = this->asset())
	{
		_columnTableWidget->setRowCount(gridLayout->columnCount());
		for (int r = 0; r < gridLayout->columnCount(); r++)
		{
			Policy policy = gridLayout->columnPolicy(r);
			float stretch = gridLayout->columnStretch(r);
			_columnTableWidget->setRowLabel(r, r);
			_columnTableWidget->setItem(r, 0, PolicyMenu::PolicyText(policy));
			_columnTableWidget->setItem(r, 1, stretch)->setAsset(stretch);
		}
	}
}

void VBoxLayoutPanel::slotAssetChanged(BObject* object, const BValue& value)
{
	_rowSpinBox->setEnabled(false);
	_columnSpinBox->setEnabled(false);
	if (BVBoxLayout* vlayout = value)
	{
		_nameEdit->setText(vlayout->name());
		_enabledCheckBox->setChecked(vlayout->enabled());
		_marginEdit->setText(StringFromMargin(vlayout->margin()));
		_rowSpinBox->setEnabled(true);
		_rowSpinBox->setValue(vlayout->count());
		_spacingSpinBox->setValue(vlayout->spacing());
		_splitableCheckBox->setChecked(vlayout->splitable());
	}
	freshRowTableWidget();
	freshColumnTableWidget();
}

void VBoxLayoutPanel::slotNameEditFinished(BObject* object, const BValue& value)
{
	const BString& name = value;
	BLayout* layout = this->asset();
	layout->setName(name);
}
void VBoxLayoutPanel::slotEnabledToggled(BObject* object, const BValue& value)
{
	bool enabled = value;
	BLayout* layout = this->asset();
	layout->setEnabled(enabled);
}
void VBoxLayoutPanel::slotSplitableToggled(BObject* object, const BValue& value)
{
	bool splitable = value;
	BLayout* layout = this->asset();
	if (BVBoxLayout* vlayout = this->asset())
	{
		vlayout->setSplitable(splitable);
	}
	if (BHBoxLayout* hlayout = this->asset())
	{
		hlayout->setSplitable(splitable);
	}
	if (BGridLayout* gridlayout = this->asset())
	{
		gridlayout->setSplitable(splitable);
	}
}
void VBoxLayoutPanel::slotMarginEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	BMargin margin = StringToMargin(text);
	BLayout* layout = this->asset();
	layout->setMargin(margin);
}
void VBoxLayoutPanel::slotSpacingEditFinished(BObject* object, const BValue& value)
{
	int spacing = value;
	if (BVBoxLayout* vlayout = this->asset())
	{
		vlayout->setSpacing(spacing);
	}
	if (BHBoxLayout* hlayout = this->asset())
	{
		hlayout->setSpacing(spacing);
	}
	if (BGridLayout* gridLayout = this->asset())
	{
		gridLayout->setRowSpacing(spacing);
		gridLayout->setColumnSpacing(spacing);
	}
}
void VBoxLayoutPanel::slotPartItemClicked(BObject* object, const BValue& value)
{
	BComboItem* item = value;
	PartFlag part = item->value();
	if (BLayout* layout = this->asset())
	{
		layout->host()->setLayout(layout, part);
	}
}

void VBoxLayoutPanel::slotGridRowEditFinished(BObject* object, const BValue& value)
{
	if (BGridLayout* gridLayout = this->asset())
	{
		int row = value;
		gridLayout->setRowCount(row);
		freshRowTableWidget();
	}
}
void VBoxLayoutPanel::slotGridColumnEditFinished(BObject* object, const BValue& value)
{
	if (BGridLayout* gridLayout = this->asset())
	{
		int column = value;
		gridLayout->setColumnCount(column);
		freshColumnTableWidget();
	}
}
void VBoxLayoutPanel::slotTableItemRightClicked(BObject* object, const BValue& value)
{
	if (BTableItem* item = value)
	{
		if (item->column() == 0)
		{
			_policyMenu->setParent(dynamic_cast<BWidget*>(object));
			_policyMenu->setAsset(item);
			_policyMenu->setPolicy(item->asset());
			_policyMenu->setPos(item->rect().leftBottom());
			_policyMenu->popup();
			return;
		}
		if (item->column() == 1)
		{
			_stretchSpinBox->setParent(dynamic_cast<BWidget*>(object));
			_stretchSpinBox->setRect(item->rect());
			_stretchSpinBox->setValue(item->asset());
			_stretchSpinBox->setFocused(true);
			return;
		}
	}
}

void VBoxLayoutPanel::slotPolicyMenuTrigger()
{
	BTableItem* item = _policyMenu->asset();
	if (_rowTableWidget == _policyMenu->parent())
	{
		if (BGridLayout* gridLayout = this->asset())
		{
			gridLayout->setRowPolicy(item->row(), _policyMenu->policy());
		}
	}
	if (_columnTableWidget == _policyMenu->parent())
	{
		if (BGridLayout* gridLayout = this->asset())
		{
			gridLayout->setColumnPolicy(item->row(), _policyMenu->policy());
		}
	}
	item->setText(_policyMenu->title());
	item->setAsset(_policyMenu->policy());
}
void VBoxLayoutPanel::slotStretchEditFinished()
{
	BTableItem* item = _stretchSpinBox->asset();
	item->setText(_stretchSpinBox->value());
	if (_rowTableWidget == _stretchSpinBox->parent())
	{
		if (BGridLayout* gridLayout = this->asset())
			gridLayout->setRowStretch(item->row(), _stretchSpinBox->value());
	}
	if (_columnTableWidget == _stretchSpinBox->parent())
	{
		if (BGridLayout* gridLayout = this->asset())
			gridLayout->setColumnStretch(item->row(), _stretchSpinBox->value());
	}
	_stretchSpinBox->hide();
}
